package com.ds.infrastructure.hyperspace.container.internal.opentracing.reporter;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpObject;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;

/**
 * @Author: yaozh
 * @Description:
 */
@Slf4j
public class OpentracingSendChannelHandler extends SimpleChannelInboundHandler {
    private OpentracingSender opentracingSender;
    private String version;

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) {
        //Opentracing sender 目前暂时不关心响应数据
        if (msg instanceof HttpObject) {
            opentracingSender.setHealth(true);
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        if (!opentracingSender.isHealth()) {
            log.warn("Opentracing connection closed,not received any message!url:{}."
                    , opentracingSender.getUrl());
        }
        if (isRightVersion()) {
            opentracingSender.reconnection();
        }
        super.channelInactive(ctx);
    }

    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
        if (!ctx.channel().isWritable()) {
            ctx.flush().close();
            return;
        }
        super.channelWritabilityChanged(ctx);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object obj) {
        if (!isRightVersion()) {
            ctx.channel().close();
            return;
        }
        if (obj instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) obj;
            if (IdleState.WRITER_IDLE.equals(event.state())) {
                FullHttpRequest ping = opentracingSender.ping();
                /**log.info("when WRITER_IDLE,version:{}", version);*/
                if (ping != null) {
                    ctx.channel().writeAndFlush(ping);
                }
            }
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error("Occur an exception that opentracing send handler unexpected!", cause);
    }

    public void attachSender(OpentracingSender opentracingSender) {
        this.version = opentracingSender.getVersion();
        this.opentracingSender = opentracingSender;
    }

    private boolean isRightVersion() {
        return version.equals(opentracingSender.getVersion());
    }
}
